#define MIN_HEIGHT 2.0
#define MAX_HEIGHT 4.5
#define WIND vec2(0.2, 0.1)

struct vec2
{
   float x,y;
};

float fract(float x)
{
    return x-floor(x);
}

float fractal_noise(vector p)
{
    float f = 0.0;
    // add animation
    //p = p - vec3(1.0, 1.0, 0.0) * iTime * 0.1;
    p = p * 3.0;
string type = "perlin";

    f += 0.50000 * noise(type, p); p = 2.0 * p;
	f += 0.25000 * noise(type, p); p = 2.0 * p;
	f += 0.12500 * noise(type, p); p = 2.0 * p;
	f += 0.06250 * noise(type,p); p = 2.0 * p;
    f += 0.03125 * noise(type, p);
    return f;
}


float density(vector pos)
{    
    float den = 3.0 * fractal_noise(pos * 0.3) - 2.0 + (pos[1] - 2);
    float edge = 1.0 - smoothstep(MIN_HEIGHT, MAX_HEIGHT, pos[1]);
    edge *= edge;
    den *= edge;
    den = clamp(den, 0.0, 1.0);
    return den;
}

vector raymarching(vector ro, vector rd, float t, vector backCol)
{   
    vector sundir  = normalize(vector(1, 0.75, 1));
    vector sum = vector(0.0);
    float suma=0, cola=0;
    vector pos = ro + rd * t;
    for (int i = 0; i < 40; i++) {
        if (suma > 0.99 || 
            pos[1] < (MIN_HEIGHT-1.0) || 
            pos[1] > (MAX_HEIGHT+1.0)) break;
        
        float den = density(pos);
        
        if (den > 0.01) 
        {
            float dif = clamp((den - density(pos+0.3*sundir))/0.6, 0.0, 1.0);

            vector lin = vector(0.65,0.7,0.75)*1.5 + vector(1.0, 0.6, 0.3)*dif;        
            vector col =  mix( vector(1.0,0.95,0.8)*1.1, vector(0.35,0.4,0.45), den);
            cola=den;
            col *= lin;

            // front to back blending    
            cola *= 0.5;
            col *= cola;

            sum = sum + col*(1.0 - suma); 
        }
        
        t += max(0.05, 0.02 * t);
        pos = ro + rd * t;
    }
    
    sum = clamp(sum, 0.0, 1.0);
    
    float h = rd[1];
    sum = mix(sum, backCol, exp(-20.*h*h) );
    
    return mix(backCol, sum, suma);
}

float planeIntersect( vector ro, vector rd, float plane)
{
    float h = plane - ro[1];
    return h/rd[1];
}

matrix setCamera(vector ro, vector ta, float cr)
{
	vector cw = normalize(ta-ro);
	vector cp = vector(sin(cr), cos(cr),0.0);
	vector cu = normalize( cross(cw,cp) );
	vector cv = normalize( cross(cu,cw) );
return matrix(cu[0], cu[1], cu[2], 0, cv[0], cv[1], cv[2], 0, cw[0], cw[1], cw[2], 0, 0, 0, 0, 1);
   // return matrix( cu, cv, cw );
}

shader Add(
    color a = 0,
    color b = 0,
 float gamma = 1.0
       [[float min=0.1, float max=2, int sliderexponent=4]],
    output color c = 0)
{
    vector p = P;
    vector ro = vector(0.0, 0.0, -2.0);
    vector mo = vector(0.0);
// Rotate the camera
    vector target = vector(ro[0]+10., 1.0+mo[1]*3.0, ro[2]);
    
    vector cossin = vector(cos(mo[0]), sin(mo[1]));

    matrix rot = matrix(cossin[0], 0.0, -cossin[1], 0,
                   	0.0, 1.0, 0.0, 0,
                   	cossin[1], 0.0, cossin[0],0,
                       0,0,0,1
                       );

    target = rot * (target - ro) + ro;
    
    point Q = point ("object", 0, 0, 0);
    c = a + b + Q;
}